package com.btpn.custody.entity;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import com.btpn.custody.common.Constant;
import com.btpn.infra.entity.AEntityString;

@Entity
@org.hibernate.annotations.Entity(dynamicInsert=true, dynamicUpdate=true)
@Table(name = "T_CIF")
@NamedQueries({
				@NamedQuery(name  = "MasterData.findBySIDStatus",
						query = "FROM MasterData md WHERE md.sid = :sid AND" +
								" md.STATUS_MD IN (:status1, :status2)"),
						
				
				@NamedQuery(name  = "MasterData.findByStatus",
							query = "FROM MasterData md WHERE md.STATUS_MD = :status"),

				@NamedQuery(name  = "MasterData.findByStatuses2",
							query = "FROM MasterData md WHERE md.STATUS_MD IN (:status1, :status2)"),
							
				@NamedQuery(name  = "MasterData.findByStatuses3",
							query = "FROM MasterData md WHERE md.STATUS_MD IN (:status1, :status2) "+
									"AND md.CIF.OPEN_DATE BETWEEN :from AND :to"),
//									"AND md.ACCOUNT_OPEN BETWEEN :from AND :to"),

				@NamedQuery(name  = "MasterData.findByAreaIdWith2Status",
							query = "FROM MasterData md WHERE md.branch.area.id =:areaId AND md.STATUS_MD IN (:status1, :status2)"),
				@NamedQuery(name  = "MasterData.findByAreaIdWith2StatusDate",
							query = "FROM MasterData md WHERE md.branch.area.id =:areaId AND md.STATUS_MD IN (:status1, :status2) " +
									"AND md.SEND_EQ_DATE BETWEEN :from AND :to " +
									"ORDER BY md.CIF.CUSTOMER_TYPE"),
				@NamedQuery(name  = "MasterData.findByBranchIdWith2StatusDate",
							query = "FROM MasterData md WHERE md.branch.id =:branchId AND md.STATUS_MD IN (:status1, :status2) " +
									"AND md.SEND_EQ_DATE BETWEEN :from AND :to " +
									"ORDER BY md.CIF.CUSTOMER_TYPE"),
				@NamedQuery(name  = "MasterData.findAllByDateSend",
							query = "FROM MasterData md WHERE md.STATUS_MD IN (:status1, :status2) " +
									"AND md.SEND_EQ_DATE BETWEEN :from AND :to " +
									"ORDER BY md.CIF.CUSTOMER_TYPE"),

				@NamedQuery(name  = "MasterData.findByNasabahType",
							query = "FROM MasterData md WHERE md.CIF.CUSTOMER_TYPE= :nasabahType"),

				@NamedQuery(name  = "MasterData.findByBranchId",
							query = "FROM MasterData md WHERE md.branch.id = :branchId"),
				@NamedQuery(name  = "MasterData.findByBranchIdWithStatus",
							query = "FROM MasterData md WHERE md.branch.id = :branchId AND md.STATUS_MD = :status"),
				@NamedQuery(name  = "MasterData.findByBranchIdWith2Status",
							query = "FROM MasterData md WHERE md.branch.id = :branchId AND md.STATUS_MD IN (:status1, :status2)"),

				@NamedQuery(name  = "MasterData.findByNotInStatuses2",
							query = "FROM MasterData md WHERE md.STATUS_MD NOT IN (:status1, :status2)"),
				@NamedQuery(name  = "MasterData.findByNotInStatuses2DateRange",
							query = "FROM MasterData md WHERE md.STATUS_MD NOT IN (:status1, :status2) " +
									"AND md.CIF.OPEN_DATE BETWEEN :from AND :to"),

				@NamedQuery(name  = "MasterData.findByNotInStatuses3",
							query = "FROM MasterData md WHERE md.STATUS_MD NOT IN (:status1, :status2, :status3)"),

//				@NamedQuery(name  = "MasterData.findByBranchIdWithNotInStatuses2",
//							query = "FROM MasterData md WHERE md.branch.id = :branchId " +
//									"AND md.STATUS_MD NOT IN (:status1, :status2)"),

				@NamedQuery(name  = "MasterData.findByNotInStatuses3WithDateRange",
							query = "FROM MasterData md WHERE md.STATUS_MD NOT IN (:status1, :status2, :status3) AND md.CIF.OPEN_DATE BETWEEN :from AND :to"),

				@NamedQuery(name  = "MasterData.findByCif",
							query = "FROM MasterData md WHERE md.CIF.cifSid = :cif"),

				@NamedQuery(name  = "MasterData.findByStatusBranchCode",
							query = "FROM MasterData md WHERE md.STATUS_MD = :status AND md.CIF.BRANCH = :branchCode")
})
public class MasterData extends AEntityString {

	/*=============================================== C O N S T A N T =========================================*/
	private static final long serialVersionUID = 2860697343389415531L;
	public static final String NQ__FIND_BY__SID__STATUS 						= "MasterData.findBySIDStatus";
	public static final String NQ__FIND_BY__STATUS 								= "MasterData.findByStatus";

	public static final String NQ__FIND_BY__STATUSES_2							= "MasterData.findByStatuses2";
	public static final String NQ__FIND_BY__STATUSES_3							= "MasterData.findByStatuses3";
	public static final String NQ__FIND_BY__AREA_ID_WITH_2_STATUS				= "MasterData.findByAreaIdWith2Status";
	public static final String NQ__FIND_BY__AREA_ID_WITH_2_STATUS_DATE			= "MasterData.findByAreaIdWith2StatusDate";
	public static final String NQ__FIND_BY__BRANCH_ID_WITH_2_STATUS_DATE		= "MasterData.findByBranchIdWith2StatusDate";
	public static final String NQ__FIND_BY__ALL_BY_DATE_SEND					= "MasterData.findAllByDateSend";

	public static final String NQ__FIND_BY__NOT_IN_STATUSES_2					= "MasterData.findByNotInStatuses2";
	public static final String NQ__FIND_BY__NOT_IN_STATUSES_2_DATE_RANGE		= "MasterData.findByNotInStatuses2DateRange";

	public static final String NQ__FIND_BY__NOT_IN_STATUSES_3					= "MasterData.findByNotInStatuses3";

	public static final String NQ__FIND_BY__NASABAH_TYPE 						= "MasterData.findByNasabahType";

	public static final String NQ__FIND_BY__BRANCH_ID 							= "MasterData.findByBranchId";

	public static final String NQ__FIND_BY__BRANCH_ID_WITH_STATUS				= "MasterData.findByBranchIdWithStatus";
	public static final String NQ__FIND_BY__BRANCH_ID_WITH_2_STATUS				= "MasterData.findByBranchIdWith2Status";

//	public static final String NQ__FIND_BY__BRANCH_ID_WITH_NOT_IN_STATUSES_2	= "MasterData.findByBranchIdWithNotInStatuses2";

	public static final String NQ__FIND_BY__NOT_IN_STATUSES_3_DATE_RANGE 		= "MasterData.findByNotInStatuses3WithDateRange";

	//this.
	public static final String NQ__FIND_BY__CIF 								= "MasterData.findByCif";

	public static final String NQ__FIND_BY__STATUS_BRANCHCODE					= "MasterData.findByStatusBranchCode";

	/*=============================================== M E M B E R =============================================*/
	// RELATION
	@OneToMany(cascade = {CascadeType.ALL}, mappedBy = "masterData")
	private List<Address> addresses = new ArrayList<Address>();

	@OneToMany(cascade = {CascadeType.ALL}, mappedBy = "masterData", fetch = FetchType.EAGER)
	private List<Account> accounts = new ArrayList<Account>();

	@OneToOne(cascade = CascadeType.ALL)													//FK : can be md.getCIF()
	@JoinColumn(name="CIF_SID", columnDefinition="VARCHAR(6)")
	private CIF CIF;

	@ManyToOne()
	@JoinColumn(name="BRANCH_ID")								// would be related at validate
	private Branch branch;

	/* NEW:0,
	 * (NPY:1, FAIL:-1 = not relate with branch yet),
	 * RECEIVED:2,
	 * (IN_PROGRESS:3, TBO:-3),
	 * WAIT_APPROVAL:4,
	 * APPROVED:5, REJECT:-5
	 * SUCCESS_UPLOAD:6, FAIL_UPLOAD:-6
	 *
	 * 	NEW 					: just copy, not to be related yet
	 *  NOT PROCESS YET (NPY)	: success related with branch
	 * 		RECEIVED			: if docs sudah diterima (user manual change)
	 * 			if lengkap 		: IN PROGRESS	(then validate)
	 * 				[validation process]
	 *  			if complete	: WAIT_APPROVAL
	 *  				APPROVED
	 *  			if not		: IN PROGRESS
	 *  		if not			: TBO
	 *  FAIL					: fail relate with branch caused by branch not found or code null
	 *
	 */
	@Column(name = "STATUS_MD", columnDefinition="VARCHAR(2)")
	private String STATUS_MD = Constant.STATUS__MD_NEW;

	@Column(name = "STATUS_MD_MSG", columnDefinition="VARCHAR(4000)")
	private String STATUS_MD_MSG = "-";

	// RECEIVED
	@Column(name = "RECEIVED_USER", columnDefinition="VARCHAR(20)")
	private String RECEIVED_USER;
	@Column(name = "RECEIVED_DATE")
	private Date RECEIVED_DATE;

	@Column(name = "LAST_CHECK_USER", columnDefinition="VARCHAR(20)")
	private String LAST_CHECK_USER;

	// PROGRESS, next change to COMPLETED
	@Column(name = "PROGRESS_USER", columnDefinition="VARCHAR(20)")
	private String PROGRESS_USER;
	@Column(name = "PROGRESS_DATE")
	private Date PROGRESS_DATE;

	// TBO
	@Column(name = "TBO_USER", columnDefinition="VARCHAR(20)")
	private String TBO_USER;
	@Column(name = "TBO_DATE")
	private Date TBO_DATE;

	// WAIT_APPROVAL
	@Column(name = "WAIT_APPROVAL_USER", columnDefinition="VARCHAR(20)")
	private String WAIT_APPROVAL_USER;
	@Column(name = "WAIT_APPROVAL_DATE")
	private Date WAIT_APPROVAL_DATE;

	// APPROVAL
	@Column(name = "APPROVED_USER", columnDefinition="VARCHAR(20)")
	private String APPROVED_USER;
	@Column(name = "APPROVED_DATE")
	private Date APPROVED_DATE;
//	@Column(name = "REJECT", columnDefinition="VARCHAR(20)")
//	private String APPROVED_USER;

	// EQ
	@Column(name = "SEND_EQ_DATE")
	private Date SEND_EQ_DATE;
	@Column(name = "FAIL_UPLOAD_REASON")
	private String FAIL_UPLOAD_REASON;

	// SLA
	@Column(name = "SLA_BEGIN_DATE")
	private Date beginDate;
	@Column(name = "SLA_END_DATE")
	private Date endDate;
	/* -2	: outOfDate	-> telat 2hari
	 * +2	: on time	-> 2hr early
	 */
	@Column(name = "GRADE_VALUE")
	private Long gradeValue;
	/* 1	: complete at validation (default)										?
	 * 0	: email have been send & received, waiting for completing process		?
	 * +	: complete with on time
	 * - 	: complete with late
	 */
	@Column(name = "STATUS_SLA", columnDefinition="CHAR(1)")
	private String STATUS_SLA;


	/*=============================================== G E T T E R   &   S E T T E R ===========================*/
	public CIF getCIF() {
		return CIF;
	}

	public void setCIF(CIF cIF) {
		CIF = cIF;
	}

	public String getSTATUS_MD() {
		return STATUS_MD;
	}

	public void setSTATUS_MD(String sTATUS_MD) {
		STATUS_MD = sTATUS_MD;
	}

	public String getSTATUS_MD_MSG() {
		return STATUS_MD_MSG;
	}

	public void setSTATUS_MD_MSG(String sTATUS_MD_MSG) {
		STATUS_MD_MSG = sTATUS_MD_MSG;
	}

	public String getRECEIVED_USER() {
		return RECEIVED_USER;
	}

	public void setRECEIVED_USER(String rECEIVED_USER) {
		RECEIVED_USER = rECEIVED_USER;
	}

	public Date getRECEIVED_DATE() {
		return RECEIVED_DATE;
	}

	public void setRECEIVED_DATE(Date rECEIVED_DATE) {
		RECEIVED_DATE = rECEIVED_DATE;
	}

	public String getPROGRESS_USER() {
		return PROGRESS_USER;
	}

	public void setPROGRESS_USER(String pROGRESS_USER) {
		PROGRESS_USER = pROGRESS_USER;
	}

	public Date getPROGRESS_DATE() {
		return PROGRESS_DATE;
	}

	public void setPROGRESS_DATE(Date pROGRESS_DATE) {
		PROGRESS_DATE = pROGRESS_DATE;
	}

	public String getLAST_CHECK_USER() {
		return LAST_CHECK_USER;
	}

	public void setLAST_CHECK_USER(String lAST_CHECK_USER) {
		LAST_CHECK_USER = lAST_CHECK_USER;
	}

	public String getTBO_USER() {
		return TBO_USER;
	}

	public void setTBO_USER(String tBO_USER) {
		TBO_USER = tBO_USER;
	}

	public Date getTBO_DATE() {
		return TBO_DATE;
	}

	public void setTBO_DATE(Date tBO_DATE) {
		TBO_DATE = tBO_DATE;
	}

	public String getWAIT_APPROVAL_USER() {
		return WAIT_APPROVAL_USER;
	}

	public void setWAIT_APPROVAL_USER(String wAIT_APPROVAL_USER) {
		WAIT_APPROVAL_USER = wAIT_APPROVAL_USER;
	}

	public Date getWAIT_APPROVAL_DATE() {
		return WAIT_APPROVAL_DATE;
	}

	public void setWAIT_APPROVAL_DATE(Date wAIT_APPROVAL_DATE) {
		WAIT_APPROVAL_DATE = wAIT_APPROVAL_DATE;
	}

	public String getAPPROVED_USER() {
		return APPROVED_USER;
	}

	public void setAPPROVED_USER(String aPPROVED_USER) {
		APPROVED_USER = aPPROVED_USER;
	}

	public Date getAPPROVED_DATE() {
		return APPROVED_DATE;
	}

	public void setAPPROVED_DATE(Date aPPROVED_DATE) {
		APPROVED_DATE = aPPROVED_DATE;
	}

	public Date getBeginDate() {
		return beginDate;
	}

	public void setBeginDate(Date beginDate) {
		this.beginDate = beginDate;
	}

	public Date getEndDate() {
		return endDate;
	}

	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}

	public Long getGradeValue() {
		return gradeValue;
	}

	public void setGradeValue(Long gradeValue) {
		this.gradeValue = gradeValue;
	}

	public Date getSEND_EQ_DATE() {
		return SEND_EQ_DATE;
	}

	public void setSEND_EQ_DATE(Date sEND_EQ_DATE) {
		SEND_EQ_DATE = sEND_EQ_DATE;
	}

	public String getSTATUS_SLA() {
		return STATUS_SLA;
	}

	public void setSTATUS_SLA(String sTATUS_SLA) {
		STATUS_SLA = sTATUS_SLA;
	}

	public Branch getBranch() {
		return branch;
	}

	public void setBranch(Branch branch) {
		this.branch = branch;
	}

	public List<Address> getAddresses() {
		return addresses;
	}

	public void setAddresses(List<Address> addresses) {
		this.addresses = addresses;
	}

	public List<Account> getAccounts() {
		return accounts;
	}

	public void setAccounts(List<Account> accounts) {
		this.accounts = accounts;
	}

	public String getFAIL_UPLOAD_REASON() {
		return FAIL_UPLOAD_REASON;
	}

	public void setFAIL_UPLOAD_REASON(String fAIL_UPLOAD_REASON) {
		FAIL_UPLOAD_REASON = fAIL_UPLOAD_REASON;
	}
}